package com.xykj.service.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.xykj.common.entry.NewsFlash;
import com.xykj.mapper.NewsFlashMapper;
import com.xykj.service.FCrawlerService;
import com.xykj.web.websocket.NewsWebSocketHandler;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 证券快讯爬虫类
 */
@Slf4j
@Service
public class NewsFlashCrawlerService implements FCrawlerService {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private NewsFlashMapper newsFlashMapper;

    @Autowired
    private NewsWebSocketHandler webSocketHandler;

    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private static final String API_URL = "https://np-weblist.eastmoney.com/comm/web/getFastNewsList?client=web&biz=web_724&fastColumn=102&sortEnd=&pageSize=50&_=" + System.currentTimeMillis();

    /**
     * 证券快讯爬虫服务
     * <p>
     * 实现步骤：
     * 1. 使用Jsoup定时请求东方财富网API获取JSONP数据。
     * 2. 解析返回的JSONP数据，提取新闻列表信息。
     * 3. 批量删除旧数据并插入新数据到数据库。
     * 4. 通过WebSocket广播最新数据给前端。
     * <p>
     * 关键点：动态时间戳URL、JSONP解析、批量数据库操作、定时任务、WebSocket推送。
     */

    @Override
    @Scheduled(fixedRate = 60000)
    @Transactional(rollbackFor = Exception.class)
    public boolean crawl() {
        log.info("开始爬取证券快讯...");
        try {
            // 动态生成时间戳
            long timestamp = System.currentTimeMillis();
            // 构建动态URL
            String apiUrl = "https://np-weblist.eastmoney.com/comm/web/getFastNewsList?client=web" + "&biz=web_724&fastColumn=102&sortEnd=&pageSize=50&" +
                    "req_trace=" + timestamp + "&_=" + timestamp + "&callback=jQuery18309827094102397353_" + timestamp;
            // 1. 发送HTTP请求获取JSONP数据
            String jsonpResponse = Jsoup.connect(apiUrl)
                    .ignoreContentType(true)
                    .method(Connection.Method.GET)
                    .execute()
                    .body();
            // 2. 提取JSON部分（去掉JSONP包装）
            String json = jsonpResponse.substring(
                    jsonpResponse.indexOf('(') + 1,
                    jsonpResponse.lastIndexOf(')')
            );
            // 3. 使用Gson解析JSON
            JsonObject root = JsonParser.parseString(json).getAsJsonObject();
            if (!root.get("code").getAsString().equals("1")) {
                System.err.println("API返回错误码: " + root.get("code").getAsString());
                return false;
            }
            JsonObject data = root.getAsJsonObject("data");
            List<NewsFlash> stockNewses = parseStockNews(data);
            // 4. 保存到数据库
            int maxRecords = 100;
            List<NewsFlash> savedList = stockNewses.subList(0, Math.min(maxRecords, stockNewses.size()));
            if (savedList.isEmpty()) {
                log.warn("未解析到有效的股票快讯数据");
                return false;
            }
            List<Long> longs = newsFlashMapper.selectExistingIds();
            if (!longs.isEmpty()) {
                newsFlashMapper.batchDelete(longs);
            }
            // 批量插入新数据
            newsFlashMapper.batchInsert(savedList);
            // ✅ 在这里调用 WebSocket 推送
            // WebSocket推送
            webSocketHandler.broadcast(savedList);
            log.info("成功保存 {} 条股票快讯数据到数据库", savedList.size());
            return true;
        } catch (Exception e) {
            log.error("快讯爬取失败", e);
        }
        return false;
    }

    private List<NewsFlash> parseStockNews(JsonObject data) {
        List<NewsFlash> result = new ArrayList<>();
        LocalDateTime now = LocalDateTime.now();

        // 解析fastNewsList数组
        JsonArray newsList = data.getAsJsonArray("fastNewsList");
        newsList.forEach(element -> {
            JsonObject item = element.getAsJsonObject();
            NewsFlash news = new NewsFlash();
            // 解析基础字段
            news.setTitle(item.get("title").getAsString()); // 标题
            news.setPublishTime(parseDate(item.get("showTime").getAsString())); // 发布时间
            // 可选字段处理（根据实际需求补充）
            news.setContent(item.get("summary").getAsString());
            news.setCreatedAt(now);
            news.setUpdatedAt(now);
            result.add(news);
        });
        return result;
    }

    // "2025-06-02 23:35:25" 格式转换
    private LocalDateTime parseDate(String dateStr) {
        if (dateStr == null || dateStr.trim().isEmpty()) {
            throw new IllegalArgumentException("Date string cannot be null or empty");
        }

        try {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            return LocalDateTime.parse(dateStr, formatter);
        } catch (DateTimeParseException e) {
            throw new IllegalArgumentException("Invalid date format. Expected format: yyyy-MM-dd HH:mm:ss", e);
        }
    }

}